/*
 * Copyright (C) 2015 Realtek Semiconductor Corp.
 * All Rights Reserved.
 *
 * This program is the proprietary software of Realtek Semiconductor
 * Corporation and/or its licensors, and only be used, duplicated,
 * modified or distributed under the authorized license from Realtek.
 *
 * ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER
 * THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
 *
 * Purpose : OMCI driver feature module
 *
 * Feature : Reverse FE/GE port sequence
 */

/*
 * Include Files
 */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <DRV/omci_drv.h>
#include <common/error.h>

#include <rtk/switch.h>

static signed customOpt = -1;
module_param (customOpt, int, S_IRUSR);

/*
 * Data Declaration
 */

/*
 * Function Declaration
 */


static unsigned int apply_port_remapping(va_list argp)
{
	uint8                   portId, *pTotalUniPort = NULL;
	int32                   phyPortId, cur_custom_type;
    uint32                  api_opt_id;
    omci_dev_capability_t   *p = NULL;
    uint8 fePortNum = 0, gePortNum = 0, eth2p5gPortNum = 0, xePortNum = 0;

    cur_custom_type = va_arg(argp, int32);
    api_opt_id      = va_arg(argp, uint32);
    p       		= va_arg(argp, omci_dev_capability_t *);
	pTotalUniPort	= va_arg(argp, uint8 *);
    va_end(argp);

 //   if (cur_custom_type != customOpt)
 //       return OMCIDRV_FEATURE_ERR_OK;

    if (0 != api_opt_id)
        return OMCIDRV_FEATURE_ERR_OK;

	// follow upper layer defined
    for (portId = 0; portId < *pTotalUniPort; portId++)
    {
        phyPortId = gDrvCtrl.portRemap[portId];


        if (OMCI_ETH_PORT_NONE == p->ethPort[phyPortId].portType)
            continue;

        // portIdInType record upper layer logical id, it is not switch logical id
        OMCI_LOG(OMCI_LOG_LEVEL_WARN, "%s portId=%d,  phyPortId:%d ,portType:%d", __FUNCTION__, 
            portId, phyPortId, p->ethPort[phyPortId].portType);


        if (OMCI_ETH_PORT_FE == p->ethPort[phyPortId].portType)
        {
            p->ethPort[phyPortId].portIdInType = fePortNum++;
    
        }
    
        else if (OMCI_ETH_PORT_GE == p->ethPort[phyPortId].portType)
        {
            p->ethPort[phyPortId].portIdInType = gePortNum++;
    
        }

        else if (OMCI_ETH_PORT_2P5GE == p->ethPort[phyPortId].portType)
        {
            p->ethPort[phyPortId].portIdInType = eth2p5gPortNum++;

        }

        else if (OMCI_ETH_PORT_XE == p->ethPort[phyPortId].portType)
        {
            p->ethPort[phyPortId].portIdInType = xePortNum++;
    
        }        

    }

	return OMCIDRV_FEATURE_ERR_OK;
}

static feature_kapi_t feature_api_entry =
{
    .regApiId       = FEATURE_KAPI_ME_00020000,
    .regCB          = apply_port_remapping,
    .regModuleName  = "apply_port_remapping",
};

int __init omci_apply_port_remapping_init(void)
{
	if (OMCIDRV_FEATURE_ERR_OK != omcidrv_feature_register(&feature_api_entry))
    {
        printk("%s() init failed\n", __FUNCTION__);

        return -1;
    }

	return 0;
}

void __exit omci_apply_port_remapping_exit(void)
{
    feature_kapi_t  entry;

    memset(&entry, 0, sizeof(feature_kapi_t));
    entry.regApiId = FEATURE_KAPI_ME_00020000;
    entry.regCB = NULL;

	if (OMCIDRV_FEATURE_ERR_OK != omcidrv_feature_unregister(&entry))
    {
        printk("%s() exit failed\n", __FUNCTION__);
    }
}

/*
 * Symbol Definition
 */

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("RealTek OMCI kernel module");
MODULE_AUTHOR("RealTek");
module_init(omci_apply_port_remapping_init);
module_exit(omci_apply_port_remapping_exit);
